﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tao.OpenGl;
using AvantGameMachine.Graphics.InternalObjects;
using AvantGameMachine.Events;

namespace AvantGameMachine.Graphics
{
    public class EngineTopScene : Transformable
    {
        private List<Camera> cameras = new List<Camera>();
        private List<IRenderizableObject> ObjectsToDispose = new List<IRenderizableObject>();
        private Box viewPort;

        internal int renderizedObjects = 0;
        internal int renderLevel = 0;

        public EngineTopScene()
        {
        }

        public void Init(Box _viewPort)
        {
            viewPort = _viewPort;
        }

        internal void AddObjectToDebugRender(IRenderizableObject _object)
        {
            string temp = string.Empty;

            for (int i = 0; i < renderLevel; i++)
                temp += " ";

            temp += _object.Name + "-> " + _object.ToString();
//            AGMPlatform.DVars.SetVar<string>("RObject" + renderizedObjects, temp);
        }

        public T CreateNewCamera<T>(string _name) where T : Camera, new()
        {
            T cam = new T();
            cameras.Add(cam);
            return cam;
        }

        public T CreateNewRenderToTextureCamera<T>(string _name) where T : Camera, new()
        {
            T cam = new T();
            return cam;
        }

        internal int ScreenW
        {
            get { return viewPort.X1Int;  }
            set { viewPort.X1 = value;    }
        }

        internal int ScreenH
        {
            get { return viewPort.Y1Int; }
            set { viewPort.Y1 = value;   }
        }

        internal void InternalRender()
        {
            PreRender();
            Render();
            RenderChildren();
            PostRender();

            DisposeObjects();
        }

        public void Render()
        {
            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glLoadIdentity();
            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glLoadIdentity();
        }

        internal void RenderChildren()
        {
            foreach (Camera cam in cameras)
            {
                cam.Update();
                cam.InternalRender();
            }
        }

        internal void NewMousePos(int _x, int _y)
        {
            // Pass the new mouse pos to all available cameras.
            foreach (Camera cam in cameras)
            {
                cam.NewMousePos(_x, _y);
            }
        }

        internal void AddObjectToDispose(IRenderizableObject _obj)
        {
            lock (ObjectsToDispose)
            {
                ObjectsToDispose.Add(_obj);
            }
        }

        internal void DisposeObjects()
        {
            if (ObjectsToDispose.Count > 0)
            {
                lock (ObjectsToDispose)
                {
                    IRenderizableObject[] objArray = ObjectsToDispose.ToArray();
                    for (int i = 0; i < objArray.Length; i++)
                    {
                        if (objArray[i] != null)
                        {
                            objArray[i].Dispose();
                            objArray[i] = null;
                        }
                    }

                    ObjectsToDispose.Clear();
                }
            }
        }
    }
}
